using OpenTK.Graphics.OpenGL4;
using OpenTK.Mathematics;
using SkiaSharp;

namespace AssetImporter
{
    public interface IRender
    {
        void Logic(double deltaSeconds);
        void Render();
    }

    public class WorldRender : IRender
    {
        int countor = 0;
        int vao = 0;
        int vbo = 0;
        int ebo = 0;
        int tex = 0;
        public ICamera camera;
        int width;
        int height;
        float[] vertices;
        uint[] indices;
        Shader shader;

        Vector3 BaseCamePos;
        public WorldRender(int width, int height)
        {
            Importer.window.OnWindowReset += OnResize;
            this.width = width;
            this.height = height;

            vertices = new [] {
                0.5f,  0.5f, 0.5f,  1.0f, 1.0f,   // 右上
                0.5f, -0.5f, 0.5f,  1.0f, 0.0f,   // 右下
                -0.5f, -0.5f, 0.5f, 0.0f, 0.0f,   // 左下
                -0.5f,  0.5f, 0.5f, 0.0f, 1.0f,   // 左上

                0.5f,  0.5f, -0.5f,  1.0f, 1.0f,   // 右上
                0.5f, -0.5f, -0.5f,  1.0f, 0.0f,   // 右下
                -0.5f, -0.5f, -0.5f, 0.0f, 0.0f,   // 左下
                -0.5f,  0.5f, -0.5f, 0.0f, 1.0f,   // 左上

                0.5f,  0.5f, -0.5f,  1.0f, 1.0f,   // 右上
                0.5f,  0.5f, 0.5f,  1.0f, 0.0f,   // 右下
                -0.5f, 0.5f, 0.5f, 0.0f, 0.0f,   // 左下
                -0.5f, 0.5f, -0.5f, 0.0f, 1.0f,    // 左上

                0.5f,  -0.5f, -0.5f,  1.0f, 1.0f,   // 右上
                0.5f,  -0.5f, 0.5f,  1.0f, 0.0f,   // 右下
                -0.5f, -0.5f, 0.5f, 0.0f, 0.0f,   // 左下
                -0.5f, -0.5f, -0.5f, 0.0f, 1.0f,    // 左上

                -0.5f,  0.5f, -0.5f,  1.0f, 1.0f,   // 右上
                -0.5f,  0.5f, 0.5f,  1.0f, 0.0f,   // 右下
                -0.5f, -0.5f, 0.5f, 0.0f, 0.0f,   // 左下
                -0.5f, -0.5f, -0.5f, 0.0f, 1.0f,    // 左上

                0.5f,  0.5f, -0.5f,  1.0f, 1.0f,   // 右上
                0.5f,  0.5f, 0.5f,  1.0f, 0.0f,   // 右下
                0.5f, -0.5f, 0.5f, 0.0f, 0.0f,   // 左下
                0.5f, -0.5f, -0.5f, 0.0f, 1.0f    // 左上
            };
            
            indices = new uint[] {
                    0, 1, 3, // 第一个三角形
                    1, 2, 3, // 第二个三角形

                    4, 5, 7, // 第一个三角形
                    5, 6, 7,  // 第二个三角形

                    8, 9, 11, // 第一个三角形
                    9, 10, 11,  // 第二个三角形

                    12, 13, 15, // 第一个三角形
                    13, 14, 15,  // 第二个三角形

                    16, 17, 19, // 第一个三角形
                    17, 18, 19,  // 第二个三角形

                    20, 21, 23, // 第一个三角形
                    21, 22, 23,  // 第二个三角形
            };

            vao = GL.GenVertexArray();
            GL.BindVertexArray(vao);

            vbo = GL.GenBuffer();
            GL.BindBuffer(BufferTarget.ArrayBuffer, vbo);
            GL.BufferData(BufferTarget.ArrayBuffer, vertices.Count() * sizeof(float), vertices, BufferUsageHint.StaticDraw);

            ebo = GL.GenBuffer();
            GL.BindBuffer(BufferTarget.ElementArrayBuffer, ebo);
            GL.BufferData(BufferTarget.ElementArrayBuffer, indices.Count() * sizeof(uint), indices, BufferUsageHint.StaticDraw);

            GL.VertexAttribPointer(0, 3, VertexAttribPointerType.Float, false, 5 * sizeof(float), new IntPtr(0 * sizeof(float)));
            GL.VertexAttribPointer(1, 2, VertexAttribPointerType.Float, false, 5 * sizeof(float), new IntPtr(3 * sizeof(float)));

            GL.EnableVertexAttribArray(0);
            GL.EnableVertexAttribArray(1);

            GL.BindVertexArray(0);

            tex = LoadTexture("./bits/test.bmp");

            BaseCamePos = new Vector3(0, 5, -5);
            // camera = new PerspectiveCamera(width, height, BaseCamePos, new Vector3(0, 0, 0));
            camera = new OrthoCamera(width, height, BaseCamePos, new Vector3(0, 0, 0));
            CameraSurrendCameraOrder.camera = camera;
            CameraSurrendTargetOrder.camera = camera;
            CameraMoveOrder.camera = camera;
            CameraMoveInOrder.camera = camera;

            GL.Enable(EnableCap.DepthTest);

            shader = new TestShader();
        }

        void OnResize(int width, int height)
        {
            this.width = width;
            this.height = height;
            camera.OnResize(width, height);
        }

        public void Logic(double deltaSeconds)
        {
            countor+=3;
            countor%=359;
        }

        public void Render()
        {

            GL.BindVertexArray(vao);
            shader.UseProgram();
            GL.BindTexture(TextureTarget.Texture2D, tex);
            shader.SetMatrix4("projMatrix", camera.ProjMatrix);
            shader.SetMatrix4("viewMatrix", camera.ViewMatrix);
            Matrix4.CreateTranslation(new Vector3(0, 0, 0), out var model);
            shader.SetMatrix4("modelMatrix", model);
            GL.DrawElements(PrimitiveType.Triangles, 36, DrawElementsType.UnsignedInt, 0);
        }

        private int LoadTexture(String path)
        {
            var img = SKBitmap.FromImage(SKImage.FromEncodedData(File.OpenRead(path)));
            GL.ActiveTexture(TextureUnit.Texture0);
            var tex = GL.GenTexture();
            GL.BindTexture(TextureTarget.Texture2D, tex);
            GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba, img.Width, img.Height, 0, PixelFormat.Bgra, PixelType.UnsignedByte, img.GetPixels());

            GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, (int)TextureWrapMode.MirroredRepeat); 
            GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (int)TextureWrapMode.MirroredRepeat); 

            GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.NearestMipmapNearest);
            GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Linear);

        
            GL.GenerateMipmap(GenerateMipmapTarget.Texture2D);

            GL.BindTexture(TextureTarget.Texture2D, 0);

            return tex;
        }
    }
}
